package br.com.puertorico.common.loggin;

/**
 * Classe utilit&aacute;ria para manipular o log da aplica&ccedil;&aacute;o
 *
 * @author <a href="mailto:danielsudpr@gmail.com">Daniel Camargo</a>
 * @version 1.0
 */
public class Logger {

	/** Inst&atilde;ncia real do logger */
	private org.apache.log4j.Logger _logger;

	/**
	 * Retorna a inst&atilde;ncia do Logger. O par&acirc;metro deste
	 * m&eacute;todo deve ser <b>getClass().getName()</b>.
	 *
	 * @param className
	 *            Nome da classe que est&aacute; querendo o Logger
	 * @return Inst&acirc;ncia do Logger
	 */
	public static Logger getLogger(String className) {
		Logger result = new Logger();
		result._logger = org.apache.log4j.Logger.getLogger(className);
		return result;
	}

	/**
	 * Retorna a inst&atilde;ncia do Logger. O par&acirc;metro deste
	 * m&eacute;todo deve ser <b>getClass()</b>.
	 *
	 * @param clazz
	 *            a classe que est&aacute; querendo o Logger
	 * @return Inst&acirc;ncia do Logger
	 */
	public static Logger getLogger(Class<?> clazz) {
		Logger result = new Logger();
		result._logger = org.apache.log4j.Logger.getLogger(clazz);
		return result;
	}

	/**
	 * Escreve uma informa&ccedil;&atilde;o de debug no log.
	 *
	 * @param message
	 *            Mensagem que deve ser escrita
	 * @param params
	 *            sao os par&acirc;metros que devem ser injetados no texto a ser
	 *            escrito. Ex: a chamada debug("bla #0, bla #1", "casa",
	 *            "telefone") vai gerar a sa&iacute;da "bla casa, bla telefone".
	 */
	public void debug(Object message, Object... params) {
		if (_logger.isDebugEnabled()) {
			_logger.debug(formatLogMessage(message, params));
		}
	}

	/**
	 * Escreve uma informa&ccedil;&atilde;o de debug no log.
	 *
	 * @param message
	 *            Mensagem que deve ser escrita
	 * @param t
	 *            referece ao objeto Throwable que ser&aacute; associado
	 *            &agrave; mensagem.
	 * @param params
	 *            sao os par&acirc;metros que devem ser injetados no texto a ser
	 *            escrito.
	 */
	public void debug(Object message, Throwable t, Object... params) {
		if (_logger.isDebugEnabled()) {
			_logger.debug(formatLogMessage(message, params), t);
		}
	}

	/**
	 * Verifica se o debug est&aacute; habilitado.
	 */
	public boolean isDebugEnabled() {
		return _logger.isDebugEnabled();
	}

	/**
	 * Escreve uma informa&ccedil;&atilde;o de erro no log.
	 *
	 * @param message
	 *            Mensagem que deve ser escrita
	 * @param params
	 *            sao os par&acirc;metros que devem ser injetados no texto a ser
	 *            escrito. Ex: a chamada error("bla #0, bla #1", "casa",
	 *            "telefone") vai gerar a sa&iacute;da "bla casa, bla telefone".
	 */
	public void error(Object message, Object... params) {
		_logger.error(formatLogMessage(message, params));
	}

	/**
	 * Escreve uma informa&ccedil;&atilde;o de erro no log.
	 *
	 * @param message
	 *            Mensagem que deve ser escrita
	 * @param t
	 *            referece ao objeto Throwable que ser&aacute; associado
	 *            &agrave; mensagem.
	 * @param params
	 *            sao os par&acirc;metros que devem ser injetados no texto a ser
	 *            escrito.
	 */
	public void error(Object message, Throwable t, Object... params) {
		_logger.error(formatLogMessage(message, params), t);
	}

	/**
	 * Escreve uma informa&ccedil;&atilde;o de info no log.
	 *
	 * @param message
	 *            Mensagem que deve ser escrita
	 * @param params
	 *            sao os par&acirc;metros que devem ser injetados no texto a ser
	 *            escrito. Ex: a chamada info("bla #0, bla #1", "casa",
	 *            "telefone") vai gerar a sa&iacute;da "bla casa, bla telefone".
	 */
	public void info(Object message, Object... params) {
		if (_logger.isInfoEnabled()) {
			_logger.info(formatLogMessage(message, params));
		}
	}

	public void warn(Object message, Object... params) {
		_logger.warn(formatLogMessage(message, params));
	}

	/**
	 * Verifica se a escrita de mensagens do tipo INFO est&aacute; ativada.
	 *
	 * @return Se a escrita do tipo INFO está ativada
	 */
	public boolean isInfoEnabled() {
		return _logger.isInfoEnabled();
	}

	/**
	 *
	 * Exemplo:
	 * log.debug("Creating new order for user: #0 product: #1 quantity: #2",
	 * user.username(), product.name(), quantity);
	 */
	private static String formatLogMessage(Object msg, Object... params) {
		if (msg == null) {
			return null;
		}
		String str = msg.toString();
		if (params != null) {
			for (Object p : params) {
				if (p != null) {
					str = str.replaceFirst("#\\d+", p.toString());
				}
			}
		}
		return str;
	}
}
